<?php
class Kornak_Ssh
{
    protected $_connection;
    protected $_host;
    protected $_password;
    protected $_port    = 22;
    protected $_timeout = 10;
    protected $_user;
    
    public function __construct($host = null, $user = null, $password = null, $port = null)
    {
        if (!extension_loaded('ssh2')) {
            throw Kornak_Ssh_Exception('Kornak_Ssh class needs ssh2 PHP extension');
        }
        
        if (null !== $host) {
            $this->setHost($host);
        }
        if (null !== $user) {
            $this->setUser($user);
        }
        if (null !== $password) {
            $this->setPassword($password);
        }
        if (null !== $port) {
            $this->setPort($port);
        }
    }
    
    public function connect()
    {
        $connection = ssh2_connect($this->_host, $this->_port);
        if (false === $connection) {
            throw new Kornak_Ssh_Exception("Connection to host '$this->_host' on port $this->_port failed");
        }
        
        if (!ssh2_auth_password($connection, $this->_user, $this->_password)) {
            throw new Kornak_Ssh_Exception("Connection to host '$this->_host' on port $this->_port failed");
        }
        
        $this->_connection = $connection; 
        return true;       
    }
    
    public function disconnect()
    {
        $this->_connection = null;
    }
    
    public function execute($command)
    {
        if (!$this->isConnected()) {
            throw new Kajao_Ssh_Exception('Connection is closed');
        }
        
        $command .= '; echo "__COMMAND_FINISHED__"';
        $stream = ssh2_exec($this->_connection, $command);
        if (false === $stream) {
            return false;
        }
        
        stream_set_blocking($stream, true);
        $output    = '';
        $startTime = time();
        $endTime   = $startTime + $this->_timeout;
        while(true) {
            $output .= fread($stream, 4096);
            if ('__COMMAND_FINISHED__' == trim(substr($output, -21))) {
                $output = substr($output, 0, -21);
                break;
            }
            if (time() > $endTime) {
                throw new Kajao_Ssh_Exception('Command execution timed out');    
            }
        }
        fclose($stream);
        return $output;
    }
    
    public function getHost()
    {
        return $this->_host;
    }

    public function getPassword()
    {
        return $this->_password;
    }
    
    public function getPort()
    {
        return $this->_port;
    }
    
    public function getTimeout()
    {
        return $this->_timeout;
    }
    
    public function getUser()
    {
        return $this->_user;
    }
    
    public function isConnected()
    {
        return null !== $this->_connection;
    }
    
    public function sendFile($source, $destination, $mode = 0644)
    {
        if (!$this->isConnected()) {
            throw new Kajao_Ssh_Exception('Connection is closed');
        }
        
        return ssh2_scp_send($this->_connection, $source, $destination, $mode);
    }
    
    public function setHost($host)
    {
        $this->_host = $host;
    }

    public function setPassword($password)
    {
        $this->_password = $password;
    }

    public function setPort($port)
    {
        $this->_port = $port;
    }

    public function setTimeout($timeout)
    {
        $this->_timeout = $timeout;
    }

    public function setUser($user)
    {
        $this->_user = $user;
    }
}